#!/usr/bin/env python
#
#       Parser.py
#       
#       Copyright 2009 Ben Davis <its.hip@gmail.com>
#       
#       This program is free software; you can redistribute it and/or modify
#       it under the terms of the GNU General Public License as published by
#       the Free Software Foundation; either version 2 of the License, or
#       (at your option) any later version.
#       
#       This program is distributed in the hope that it will be useful,
#       but WITHOUT ANY WARRANTY; without even the implied warranty of
#       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#       GNU General Public License for more details.
#       
#       You should have received a copy of the GNU General Public License
#       along with this program; if not, write to the Free Software
#       Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
#       MA 02110-1301, USA.

import random

import Maps
import Ships
import TestMap as Map
import ToClient

class Parser(object):
    def __init__(self, client, clients, players):
        self.client = client
        self.clients = clients
        self.players = players
        self.commands = [ChangeMap("change map"), Connect("connect"), Disconnect("disconnect"), Login("login"), Logout("logout"), \
        Register("register"), Unregister("unregister")]

    def do(self, data):
        """Acts on data inputted"""
        commands = []
        # For each command
        for command in self.commands:
            # If the data starts with a command name
            if data.startswith(command):
                # Then add command to the list
                commands.append(command)
        # If at least one matching command was found
        if len(commands) > 0:
            commands.sort()
            commands.reverse()
            # Automatically take the longest matching command
            commands[0].run(self.client, self.clients, self.players, data[len(commands[0]):].strip())
        # If there was no matching command
        else:
            # Send an error message
            self.client.send(ToClient.Message("Couldn't find command."))

class Command(str):
    """Command base class"""
    def run(self, client, clients, players, data):
        pass

class ChangeMap(Command):
    """Changes to a new map. At the moment, restarts map but in future
    will change to a map specified by name.
    
    Format: change map"""
    
    def run(self, client, clients, players, data):
        clients.send(ToClient.Message("Changing map."))
        #for word in "Sending you lots of messages at once!".split(" "):
            #clients.send(ToClient.Message(word))
        # Loop through each player
        for player in players.values():
            # Delete their current ships
            player.ships = Ships.Ships()
            # Until they have 1 ship
            while len(player.ships.values()) < 1:
                # Generate a random coordinate on the map
                x, y = random.randint(0, Map.WIDTH - 1), random.randint(0, Map.HEIGHT - 1)
                # Check it doesn't collide with any other ships
                for other in players.values():
                    for ship in other.ships.values():
                        if ship.x == x and ship.y == y:
                            break
                else:
                    player.ships.append(Ships.Pawn(player, x, y, random.randint(0, 7)))
        # Sync all clients
        for client in clients:
            client.send(ToClient.Sync(client.player, players, Maps.Map(Map)))
            
class Disconnect(Command):
    def run(self, client, clients, players, data):
        Connect('localhost')
    
class Connect(Command):
    """Mein gott, it seems to work."""
    def run(self, client, clients, players, data):
        if data != "":
            if data.count(" ") == 1:
                address = data.split(" ")[0]
                port = int(data.split(" ")[1])
            else:
                address = str(data)
                port = 7059
                client.send(ToClient.Message("Connect: No port given, trying default (7059)."))
                
            if address.count(".") < 1 and address != "localhost":
                client.send(ToClient.Message("Connect: ["+address+"] is not a valid IP or hostname."))
            else:
                client.send(ToClient.Connect(address, port))
        else:
            client.send(ToClient.Message("Connect: No server given."))
            
class Login(Command):
    def run(self, client, clients, players, data):
        if data != "":
            if data.count(" ") == 1:
                user = data.split(" ")[0]
                password = data.split(" ")[1]
                client.send(ToClient.Login(user, password))
            else:
                client.send(ToClient.Message("Login: format is &login username password."))
        else:
            client.send(ToClient.Message("Login: format is &login username password."))
    
class Logout(Command):
    def run(self, client, clients, players, data):
        client.send(ToClient.Logout())
        client.send(ToClient.Message("Logging off."))
        
class Register(Command):
    def run(self, client, clients, players, data):
        client.send(ToClient.Register())
class Unregister(Command):
    def run(self, client, clients, players, data):
        client.send(ToClient.Unregister())

